#include "ReceiveMgr.h"
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QHostAddress>
#include <QJsonDocument>
#include <QJsonParseError>

ReceiveMgr::ReceiveMgr(IDataBaseMgr* pDBMgr,QObject *parent)
	: QThread(parent),m_pDBMgr(pDBMgr)
{
	init_All();
}

ReceiveMgr::~ReceiveMgr()
{
	this->quit();
	this->wait();
}

void ReceiveMgr::init_All()
{
	m_pStateSocket = new QUdpSocket;
	if (m_pStateSocket->bind(QHostAddress::AnyIPv4, 3344))
	{
		m_pStateSocket->joinMulticastGroup(QHostAddress("224.5.6.7"));
		connect(m_pStateSocket, &QUdpSocket::readyRead, this, &ReceiveMgr::slot_ReciveData);
	}
}

void ReceiveMgr::slot_ReciveData()
{
	while (m_pStateSocket->hasPendingDatagrams()) {
		QByteArray datagram;
		datagram.resize(m_pStateSocket->pendingDatagramSize());
		QHostAddress sender;
		quint16 senderPort;

		int nRet = m_pStateSocket->readDatagram(datagram.data(), datagram.size(),
			&sender, &senderPort);

		QJsonParseError error;
		QJsonDocument jsondoc = QJsonDocument::fromJson(datagram, &error);
		if (!jsondoc.isNull() && error.error == QJsonParseError::NoError)
		{
			if (jsondoc.isObject())
			{
				QJsonObject MainObj = jsondoc.object();
				QJsonValue dataFlag = MainObj.value("checkstate");
				if (dataFlag.toString() == QStringLiteral("stop"))
				{
					QString sIpPort = MainObj.value("ip").toString();
					m_mapNetControl.find(sIpPort).value() = false;
				}
				if (dataFlag.toString() == QStringLiteral("start"))
				{
					QString sIpPort = MainObj.value("ip").toString();
					m_mapNetControl.find(sIpPort).value() =true;
				}
			}
		}
	}
}

bool ReceiveMgr::init(QString strConnectName)
{
	if (strConnectName.isEmpty())
		return false;
	m_strConnectName = strConnectName;
	QString strSql = QString("select * from T_NET_INFO where IS_CUR = '1'");
	QVariantList NetInfoList;
	QString sError;
	//��ȡ��ǰվ �����ⲿͨ��socket
	if (m_pDBMgr->select(strSql, NetInfoList, sError, m_strConnectName))
	{
		for (int i = 0; i < NetInfoList.size(); i++)
		{
			if (NetInfoList.size() == 0)return false;
			QStringList sNetInfoLst = NetInfoList.at(i).toStringList();
			QString strID = sNetInfoLst[0];
			QString strOwnerID = sNetInfoLst[1];
			int nNetType = sNetInfoLst[3].toInt();
			QList<QPair<QString, quint16> > listIpAndPort;
			switch (nNetType)
			{
			case 0://����
			{
				QString strInfo = sNetInfoLst[4];
				QStringList strList = strInfo.split(";");
				Q_FOREACH(QString str, strList)
				{
					QStringList strInfoList = str.split(":");
					//if (strInfoList[0].isEmpty() | strInfoList[1].isEmpty())continue;
					if (strInfoList.size() == 2)
					{
						listIpAndPort.push_back(qMakePair(strInfoList[0], strInfoList[1].toUInt()));
					}
				}
			}
			break;
			case 1://ɢ��
			{
				QString strInfo = sNetInfoLst[5];
				QStringList strList = strInfo.split(";");
				Q_FOREACH(QString str, strList)
				{
					QStringList strInfoList = str.split(":");
					if (strInfoList[0].isEmpty() | strInfoList[1].isEmpty())continue;
					if (strInfoList.size() == 2)
					{
						listIpAndPort.push_back(qMakePair(strInfoList[0], strInfoList[1].toUInt()));
					}
				}
			}
			break;
			case 2://�̲�
			{
				QString strInfo = sNetInfoLst[6];
				QStringList strList = strInfo.split(";");
				Q_FOREACH(QString str, strList)
				{
					QStringList strInfoList = str.split(":");
					if (strInfoList[0].isEmpty() | strInfoList[1].isEmpty())continue;
					if (strInfoList.size() == 2)
					{
						listIpAndPort.push_back(qMakePair(strInfoList[0], strInfoList[1].toUInt()));
					}
				}
			}
			break;
			case 3://΢��
			{
				QString strInfo = sNetInfoLst[7];
				QStringList strList = strInfo.split(";");
				Q_FOREACH(QString str, strList)
				{
					QStringList strInfoList = str.split(":");
					if (strInfoList[0].isEmpty() | strInfoList[1].isEmpty())continue;
					if (strInfoList.size() == 2)
					{
						listIpAndPort.push_back(qMakePair(strInfoList[0], strInfoList[1].toUInt()));
					}
				}
			}
			break;
			default:
				break;
			}

			for (int i = 0; i < listIpAndPort.size(); i++)
			{
				QPair<QString, quint16> ippair = listIpAndPort.at(i);
				QUdpSocket* pSocket = new QUdpSocket;
				
				if (pSocket->bind(QHostAddress::AnyIPv4, ippair.second))
				{
					QHostAddress receiveStatusAddress(ippair.first);
					if (receiveStatusAddress.isMulticast())
						pSocket->joinMulticastGroup(receiveStatusAddress);
					connect(pSocket, &QUdpSocket::readyRead, this, &ReceiveMgr::slotReadyRead);
					m_listSocket.push_back(pSocket);
				}
				else
				{
					delete pSocket;
					pSocket = NULL;
				}
			}

			//������ //to do������λ ������Ϊ�״�
			strSql = QString("select T1.* from T_NET_INFO T1 where T1.OWNER_ID in(select T.ID from T_DEPLOY_UNIT T where T.PARENT_ID = '%1')").arg(strOwnerID);
			QVariantList InfoList;
			QString sInfoError;
			//��ȡ��ǰվ �����ⲿͨ��socket
			if (m_pDBMgr->select(strSql, InfoList, sInfoError, m_strConnectName))
			{
				for (int k=0;k<InfoList.size();k++)
				{
					QStringList sInfoList = InfoList.at(k).toStringList();
					QString strID1 = sInfoList[0];
					QString strOwnerID1 = sInfoList[1];
					int nNetType1 = sInfoList[3].toInt();
					switch (nNetType1)
					{
					case 0://����
					{
						QString strInfo = sInfoList[4];
						QStringList strList = strInfo.split(";");
						Q_FOREACH(QString str, strList)
						{
							QStringList strInfoList = str.split(":");
							if (strInfoList.size() == 2)
							{
								m_listTransmiter.insert(qMakePair(strInfoList[0], strInfoList[1].toUInt()));
							}
						}
					}
					break;
					case 1://ɢ��
					{
						QString strInfo = sInfoList[5];
						QStringList strList = strInfo.split(";");
						Q_FOREACH(QString str, strList)
						{
							QStringList strInfoList = str.split(":");
							if (strInfoList[0].isEmpty() | strInfoList[1].isEmpty())continue;
							if (strInfoList.size() == 2)
							{
								m_listTransmiter.insert(qMakePair(strInfoList[0], strInfoList[1].toUInt()));
							}
						}
					}
					break;
					case 2://�̲�
					{
						QString strInfo = sInfoList[6];
						QStringList strList = strInfo.split(";");
						Q_FOREACH(QString str, strList)
						{
							QStringList strInfoList = str.split(":");
							if (strInfoList[0].isEmpty() | strInfoList[1].isEmpty())continue;
							if (strInfoList.size() == 2)
							{
								m_listTransmiter.insert(qMakePair(strInfoList[0], strInfoList[1].toUInt()));
							}
						}
					}
					break;
					case 3://΢��
					{
						QString strInfo = sInfoList[7];
						QStringList strList = strInfo.split(";");
						Q_FOREACH(QString str, strList)
						{
							QStringList strInfoList = str.split(":");
							if (strInfoList[0].isEmpty() | strInfoList[1].isEmpty())continue;
							if (strInfoList.size() == 2)
							{
								m_listTransmiter.insert(qMakePair(strInfoList[0], strInfoList[1].toUInt()));
							}
						}
					}
					break;
					default:
						break;
					}
				}
			}
		}
	}
	return true;
}

void ReceiveMgr::run()
{
	while (true)
	{
		m_mutex.lock();
		if (m_listBytes.isEmpty())
		{
			m_mutex.unlock();
			msleep(300);
			continue;
		}
		QByteArray bytes = m_listBytes.front();
		m_listBytes.pop_front();
		m_mutex.unlock();
		if(m_listSocket.isEmpty())
			continue;
		QUdpSocket* pUdpSocket = m_listSocket[0];
		for (QSet<QPair<QString, quint16>>::iterator itor=m_listTransmiter.begin();itor!=m_listTransmiter.end();itor++)
		{
			QPair<QString, quint16> ipPair = *itor;
			pUdpSocket->writeDatagram(bytes, QHostAddress(ipPair.first), ipPair.second);
		}
		bytes.clear();
	}
}

void ReceiveMgr::slotReadyRead()
{
	QUdpSocket* pUdpSocket = qobject_cast<QUdpSocket*>(sender());
	if (pUdpSocket == NULL)
		return;
	while (pUdpSocket->hasPendingDatagrams()) {
		QByteArray datagram;
		datagram.resize(pUdpSocket->pendingDatagramSize());
		QHostAddress sender;
		quint16 senderPort;

		int nRet = pUdpSocket->readDatagram(datagram.data(), datagram.size(),
			&sender, &senderPort);

		QString strIpPort = QString("%1:%2").arg(sender.toString()).arg(senderPort);

		if (!m_mapNetControl.contains(strIpPort))
		{
			//Ĭ�Ͻ��տ���Ϊtrue
			m_mapNetControl[strIpPort] = true;
			send("224.4.5.6", 9777, strIpPort.toLocal8Bit());
		}

		//���տ���Ϊtrue
		if (m_mapNetControl[strIpPort])
		{
			emit upBytes(datagram);
		}
	}
}

void ReceiveMgr::send(QString ip, int port, QByteArray byte)
{
	if (!byte.isEmpty())
	{
		QUdpSocket* send = new QUdpSocket;
		send->writeDatagram(byte, QHostAddress(ip), port);
		delete send;
		send = NULL;
	}
}

void ReceiveMgr::addDownBytes(const QByteArray& bytes)
{
	QMutexLocker locker(&m_mutex);
	if (bytes.isEmpty())
		return;
	m_listBytes.push_back(bytes);
}

